import { ElMessage } from "element-plus";
import { Http } from "./http";
import type { interTable, listButton } from './type'
import { reactive, type VNode } from "vue";

export class List<T extends Record<string, any> & { id?: number | string }> extends Http {
    total: number = 0;
    limit: number = 6;
    hasPages: boolean = true;
    page_index: number = 1;
    list: T[] = reactive(this.utils_proxy_set([], (target, key, value) => {
        if (key !== 'length') {
            //支持obj.a.b.c的调用方式
            if (typeof value === 'object') {
                return this.utils_readWrite(value)
            }
        }
    }));
    reSetphone: boolean = false
    labels = reactive({} as { [key in keyof T & string]?: interTable<T, key> });
    select?: T[] = [];
    url: { page: string; delete: string; list: string; update: string } = {
        page: '',
        delete: '',
        list: '',
        update: ''
    };
    has_next: boolean = true;
    search_key: Record<string, any> = {};
    border: boolean = true
    headerAlign: 'start' | 'end' | 'left' | 'right' | 'center' | 'justify' | 'match-parent' = 'center'
    rowkey: string = 'id'
    id?: (data: T) => string
    disabledRefresh?: boolean = false
    immediateCheck: boolean = true
    finishedText: string = '没有更多了'
    actions?: ({ }: { isPhone: boolean, data: T, index: number }) => listButton<T>[]
    editButton?: (isPhone: boolean) => VNode[]
    spance: number = 10
    children?: string = ''

    getUrl(url: 'page' | 'delete' | 'list' | 'update') {
        if (this.url[url]) {
            return this.url[url]
        } else if (this.baseUrl) {
            return this.baseUrl + '/' + url
        } else {
            return ''
        }
    }
    get pageUrl() {
        return this.getUrl('page')
    }
    get deleteUrl() {
        return this.getUrl('delete')
    }
    get listUrl() {
        return this.getUrl('list')
    }
    get updateUrl() {
        return this.getUrl('update')
    }
    async onEdit(_id?: number) {
        console.log(_id)
        throw new Error('未设置编辑函数')
    }
    async onAdd(_id?: number) {
        console.log(_id)
        throw new Error('未设置新增函数')
    }
    async onInfo(_id?: number) {
        console.log(_id)
        throw new Error('未设置详情函数')
    }
    setSelectList(value: T[]) {
        this.select = value
    }
    loadingChange(value: boolean) {
        this.loading = value
    }
    defaultInputChange<U extends keyof T & string>(data: T, prop: U, value: T[U]) {
        data[prop] = value
    }
    /**
     * 滚动到底部加载更多
     */
    async next() {
        if (this.has_next) {
            await this.getPage()
            this.page_index++
        }
    }
    /**
    * 刷新并请求第page_index页
    * @param page_index 
    */
    async refresh(page_index?: number) {
        if (this.hasPages) {
            this.list.length = 0
            if (page_index && page_index > 0) this.page_index = page_index
            this.has_next = true
            await this.getPage()
        } else {
            await this.getList()
        }
    }
    /**
     * 请求数据page_index自动增加
     * @param reverse 是否翻转请求结果的数组
     * @returns 
     */
    async getPage(reverse?: boolean): Promise<T[]> {
        const res = await this.#request(this.pageUrl)
        if (!res) return []
        const list = this.aftergetPage(res.list)
        if (!list) throw new Error('list数据不存在')
        reverse ? this.list.unshift(...list) : this.list.push(...list)
        return this.list
    }

    async getList() {
        const res = await this.#request(this.listUrl)
        if (!res) return []
        this.list.length = 0
        const list = this.aftergetList(res)
        if (!list) throw new Error('list数据不存在')
        this.total = list.length
        this.list.push(...list)
        return this.list
    }

    async #request(url: string) {
        if (!url) throw new Error('请求路径不存在')
        this.loading = true
        const { limit, page_index, search_key } = this
        const res = await this.request(url, { method: 'POST', data: { size: limit, page: page_index, ...search_key } })
        if (!res) return { list: [], total: 0 }
        const { total } = res
        this.total = total
        this.has_next = total ? page_index * limit < total : false
        this.loading = false
        return res
    }

    aftergetPage(res: any) { return res }
    aftergetList(res: any) { return res }

    /**
     * 删除数据
     * @param index 数据索引
     * @param id 数据id
     * @param arg 其他参数
     * @returns 
     */
    async deleteItem(index: number, id?: undefined, arg?: Record<string, number | string | boolean>): Promise<boolean>;
    async deleteItem(index: undefined, id: number | string, arg?: Record<string, number | string | boolean>): Promise<boolean>;
    async deleteItem(index?: number, id?: number | string, arg: Record<string, number | string | boolean> = {}): Promise<boolean> {
        if (index !== undefined)
            id = this.list[index]?.id
        if (!id) return false
        const res = await this.request(this.deleteUrl, { method: 'POST', data: { id: id, ...arg }, successToast: true })
        if (res) {
            if (index !== undefined) {
                this.list.splice(index, 1)
                this.total--
            } else {
                this.refresh()
            }
            return true
        }
        return false
    }
    async deleteItems() {
        const select = this.select
        if (!select) return
        if (select.length === 0) {
            if (!window.isPhone) {
                this.showToast("当前没有选中项")
            }
            return false
        }
        await this.request(this.deleteUrl, { method: 'POST', parames: { ids: select.map(item => item.id) } });
        this.refresh()
    }
}